package unsafe;

import sun.misc.Unsafe;

import java.lang.reflect.Field;


public class UnsafeAndAqs {

	private int id;

	private String name;

	private Node head;

	private Node tail;


	private static final long idOffset;
	private static final long nameOffset;
	private static final long headOffset;
	private static final long tailOffset;

	private static Unsafe unsafe;

	static final class Node {
		int id;

		volatile Node prev;

		volatile Node next;

		public Node(){
		}

		public Node(int id){
			this.id = id;
		}

	}

	private Node enq(final Node node) {
		for (;;) {
			Node t = tail;
			if (t == null) { // Must initialize
				if (compareAndSetHead(new Node()))
					tail = head;
			} else {
				node.prev = t;
				if (compareAndSetTail(t, node)) {
					t.next = node;
					return t;
				}
			}
		}
	}

	static {
		try {
			unsafe = getUnsafe();
			idOffset = unsafe.objectFieldOffset
					(UnsafeAndAqs.class.getDeclaredField("id"));
			nameOffset = unsafe.objectFieldOffset
					(UnsafeAndAqs.class.getDeclaredField("name"));
			headOffset = unsafe.objectFieldOffset
					(UnsafeAndAqs.class.getDeclaredField("head"));
			tailOffset = unsafe.objectFieldOffset
					(UnsafeAndAqs.class.getDeclaredField("tail"));
		} catch (Exception ex) { throw new Error(ex); }
	}

	private boolean compareAndSetId(int expect, long id){
		return unsafe.compareAndSwapLong(this, idOffset, expect, id);
	}

	private boolean compareAndSetName(String expect, String name){
		return unsafe.compareAndSwapObject(this, nameOffset, expect, name);
	}

	private boolean compareAndSetHead(Node head){
		return unsafe.compareAndSwapObject(this, headOffset, null, head);
	}

	private boolean compareAndSetTail(Node expect, Node update){
		return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
	}


	public static Unsafe getUnsafe(){
		Unsafe unsafe = null;
		try {
			/***
			 * 由于直接调用Unsafe.getUnsafe()需要配置JRE获取较高权限，我们利用反射获取Unsafe中的theUnsafe来取得Unsafe的可用实例。
			 */
			Field f = Unsafe.class.getDeclaredField("theUnsafe");
			f.setAccessible(true);
			unsafe = (Unsafe) f.get(null);
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return unsafe;
	}


	public static void main(String[] args) {
		System.out.println( idOffset );
		System.out.println( nameOffset );
		System.out.println( headOffset );
		System.out.println( tailOffset );

		UnsafeAndAqs unsafeAndAqs = new UnsafeAndAqs();
		unsafeAndAqs.compareAndSetId(0, 5L);
		unsafeAndAqs.compareAndSetName(null, "zhangsan");

		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		unsafeAndAqs.enq(node1);
		unsafeAndAqs.enq(node2);
		unsafeAndAqs.enq(node3);

		System.out.println(unsafeAndAqs);

		for(Node node = unsafeAndAqs.head; node != null; node = node.next){
			System.out.println(node.id);
		}
	}
}

